package cn.gson.financial.controller;

import cn.gson.financial.annotation.IgnoresLogin;
import cn.gson.financial.common.VoucherExcelUtils;
import cn.gson.financial.extendcontroller.VoucherExtendsController;
import cn.gson.financial.kernel.controller.JsonResult;
import cn.gson.financial.kernel.exception.ServiceException;
import cn.gson.financial.kernel.model.entity.*;
import cn.gson.financial.kernel.model.mapper.FileMapper;
import cn.gson.financial.kernel.model.vo.*;
import cn.gson.financial.kernel.service.*;
import cn.gson.financial.kernel.utils.BaseUtil;
import cn.gson.financial.kernel.utils.RedisUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;


@Slf4j
@RestController
@RequestMapping("/voucher")
public class VoucherController extends VoucherExtendsController<VoucherService, Voucher> {

    String[] defaultSummary = new String[]{"提现", "利息收入", "利息收入", "支付银行手续费", "报销销售人员的业务招待费", "购入固定资产", "支付货款"};

    @Autowired
    private UserService userService;

    @Autowired
    private FileMapper fileMapper;

    @Autowired
    private AllSelectService allSelectService;

    @Autowired
    private VoucherExcelUtils excelUtils;

    @Autowired
    private VoucherDetailsService voucherDetailsService;

    @Autowired
    private VoucherDetailsAuxiliaryService voucherDetailsAuxiliaryService;

    @Autowired
    private UserRoundupsService userRoundupsService;
    @Autowired
    private FileManageController fileManageController;
    @Autowired
    private OssService ossService;
    @Autowired
    private SubjectService subjectService;
    @Autowired
    private CheckoutService checkoutService;
    @Autowired
    private RedisUtil redisUtil;

    @GetMapping("/findAuxiliaryBySubId")
    public JsonResult findAuxiliaryBySubId(@RequestParam("subjectId")Integer subjectId){
        QueryWrapper<VoucherDetails> wrapper = new QueryWrapper<>();
        wrapper.eq("subject_id",subjectId);
        return JsonResult.successful(voucherDetailsService.list(wrapper));
    }

    @PostMapping("/updateVoucherFile")
    @Transactional(rollbackFor = Throwable.class)
    public JsonResult updateVoucherFile(@RequestParam("accountSetsId")int accountSetsId,@RequestParam("voucherId")int voucherId,
                                        @RequestPart("delFileIdList") List<String> delFileIdList,@RequestPart("fileList") List<MultipartFile> fileList){
        String result = "";
        //处理要删除的附件
        if (delFileIdList == null || delFileIdList.size() == 0){
            //说明本次修改凭证时没有删除附件，不做任何处理
        }else {
            //需要删除oss上的文件，同时删除数据表fxy_finacnial_file中的数据
            for (String fileId : delFileIdList) {
               ossService.deleteFile(fileId);
            }
            //删除数据表fxy_finacnial_file中的数据
            fileMapper.delFileList(delFileIdList);
            result += "附件删除成功！";
        }

        //处理新上传的附件
        if (fileList == null || fileList.size() == 0){
            //说明本次修改凭证时没有新增附件，不做任何处理
        }else {
            //需要上传附件，同时给数据表fxy_finacnial_file中插入数据
            FileBean fileBean = new FileBean();
            fileBean.setFileList(fileList);
            fileBean.setAccountSetsId(accountSetsId);
            fileBean.setVoucherId(voucherId);
            fileManageController.uploadAppendix(fileBean);
            result += "附件上传成功！";
        }
        //同步附单据数到凭证数据库中
        fileMapper.updateVoucherDocNum(accountSetsId,voucherId);

        List<FileBean> fileBeanList = fileMapper.findFileBean(accountSetsId, voucherId);
        HashMap<Object, Object> hashMap = new HashMap<>();
        hashMap.put("uploadResult",result);
        hashMap.put("fileBeanList",fileBeanList);

        return JsonResult.successful(hashMap);
    }

    /**
     * 序时账 动态查询
     */
    @IgnoresLogin
    @GetMapping("/getChronologicalAccount")
    public JsonResult getChronologicalAccount(
                                                String sTime,
                                                String eTime,
                                                String wordCode,
                                                String word,
                                                String summary,
                                                String createMemberName,
                                                String subjectCode,
                                                String sMoney,
                                                String eMoney,
                                                Integer sort,
                                                Integer currencyId){

        return JsonResult.successful(
                voucherDetailsService.selectChronologicalAccountByCurrencyParam(
                        this.accountSetsId, sTime, eTime, wordCode,word, summary,createMemberName,
                        subjectCode,sMoney,eMoney, sort,currencyId
                )
        );
    }

    /**
     * 核算项目明细账   -----  核算项目余额 查看某个客户的明细账通用
     * @param accSetsId
     * @param subjectCode
     * @param sTime
     * @param eTime
     * @param categoryId
     * @param categoryCode
     * @return
     */
    @IgnoresLogin
    @GetMapping("/selectAISLByParams")
    public JsonResult selectAISLByParams(Integer accSetsId,
                                         String subjectCode,
                                         String sTime,
                                         String eTime,
                                         Integer categoryId,
                                         String categoryCode){
        String sSubjectCode=subjectCode;
        String eSubjectCode="";
        if(BaseUtil.checkValueIsNull(subjectCode).contains("-")){
            String[] sry = subjectCode.split("-");
            sSubjectCode = sry[0];
            eSubjectCode = sry[1];
        }else if(BaseUtil.checkValueIsNull(subjectCode).contains(",")){
            String[] sry = subjectCode.split(",");
            sSubjectCode = sry[0];
            eSubjectCode = sry[1];
        }
        return JsonResult.successful(voucherDetailsAuxiliaryService.selectAISLByParams(accSetsId, sSubjectCode, eSubjectCode,sTime,eTime,categoryId,categoryCode));
    }

    @PostMapping("/list")
    public JsonResult voucherList(@RequestBody VoucherSelectVo vo){
        log.info("凭证列表参数："+vo);
        List<Voucher> voucherList = allSelectService.voucherSelect(vo,accountSetsId);
        List<Integer> voucherIdList = new ArrayList<>();
        for (Voucher voucher : voucherList) {
            voucherIdList.add(voucher.getId());
        }
        if (voucherIdList.size()>0){
            List<FileBean> fileNameList = fileMapper.findFileNameList(voucherList.get(0).getAccountSetsId(), voucherIdList);

            Map<Integer, List<FileBean>> collect = fileNameList.stream().collect(Collectors.toMap(FileBean::getVoucherId,e -> {
                        List<FileBean> auxiliaryVos = new ArrayList<>();
                        auxiliaryVos.add(e);
                        return auxiliaryVos;
                    },
                    (List<FileBean> oldList, List<FileBean> newList) -> {
                        oldList.addAll(newList);
                        return oldList;
                    }));

            List<VoucherFileNameVo> voucherFileNameVos = new ArrayList<>();
            for (Voucher voucher : voucherList) {
                VoucherFileNameVo voucherFileNameVo = new VoucherFileNameVo();
                List<FileBean> fileBeans = collect.get(voucher.getId());
                voucherFileNameVo.setVoucher(voucher);
                voucherFileNameVo.setFileBeanList(fileBeans);
                voucherFileNameVos.add(voucherFileNameVo);
            }
            return JsonResult.successful(voucherFileNameVos);
        }else {
            return JsonResult.successful(null);
        }
    }

    @PostMapping("/getCreate")
    public JsonResult getCreate(@RequestBody List<VoucherCreateVo> vo){
        return JsonResult.successful(allSelectService.selectCreateMember(vo));
    }


    @GetMapping("code")
    public JsonResult loadCode(String word, Date currentAccountDate) {
        int code = this.service.loadCode(this.accountSetsId, word, currentAccountDate);
        return JsonResult.successful(code);
    }

    /**
     * 期末结转，结转金额
     *
     * @param years 期间年
     * @param month 期间月
     * @param code  科目编码
     * @return
     */
    @PostMapping("carryForwardMoney")
    public JsonResult carryForwardMoney(Integer years, Integer month, String[] code) {
        Map<String, VoucherDetails> detailsMap = this.service.carryForwardMoney(this.accountSetsId, years, month, code);
        return JsonResult.successful(detailsMap);
    }

    @PostMapping("closingCarryover")
    public JsonResult closingCarryover(Integer years, Integer month) {
        Map<Integer, Double> detailsMap = this.service.closingCarryover(this.accountSetsId, years, month);
        return JsonResult.successful(detailsMap);
    }


    /**
     * 断号整理
     *
     * @param year  期间年
     * @param month 期间月
     * @return
     */
    @GetMapping("finishingOffNo")
    public JsonResult finishingOffNo(Integer year, Integer month) {
        this.service.finishingOffNo(this.accountSetsId, year, month);
        return JsonResult.successful();
    }

    /**
     * 批量删除
     *
     * @param checked 凭证ID
     * @return
     */
    @PostMapping("batchDelete")
    public JsonResult batchDelete(Integer[] checked, Integer year, Integer month) {
        this.service.batchDelete(this.accountSetsId, checked, year, month);
        return JsonResult.successful();
    }
    /**
     * 批量删除---改
     *
     * @param
     * @return
     */
    @PostMapping("/delete")
    public JsonResult delete(@RequestBody VoucherIdVo vo) {

        userRoundupsService.deleteVoucher(vo);
        return JsonResult.successful();
    }
    /**
     * 批量审核
     *
     * @param checked 凭证ID
     * @return
     */
    @PostMapping("audit")
    public JsonResult audit(Integer[] checked, Integer year, Integer month) {
        this.service.audit(this.accountSetsId, checked, this.currentUser, year, month);
        return JsonResult.successful();
    }
    @PostMapping("/auditNew")
    public JsonResult auditNew(@RequestBody AuditVo vo) {

        vo.setAuditDate(new Date());
        int flag = userRoundupsService.auditNew(vo,this.accountSetsId);
        return JsonResult.successful(flag);
    }
    /**
     * 批量反审核
     *
     * @param checked 凭证ID
     * @return
     */
    @PostMapping("cancelAudit")
    public JsonResult cancelAudit(Integer[] checked, Integer year, Integer month) {
        this.service.cancelAudit(this.accountSetsId, checked, this.currentUser, year, month);
        return JsonResult.successful();
    }


    @PostMapping("cancelAuditNew")
    public JsonResult cancelAuditNew(@RequestBody VoucherIdVo vo) {
        int flag = userRoundupsService.cancelAuditNew(vo,this.accountSetsId);
        return JsonResult.successful(flag);
    }
    /**
     * 上一条
     *
     * @param currentId 凭证ID
     * @return
     */
    @GetMapping("beforeId")
    public JsonResult beforeId(Integer currentId) {
        Integer id = this.service.getBeforeId(this.accountSetsId, currentId);
        return JsonResult.successful(id);
    }

    /**
     * 下一条
     *
     * @param currentId 凭证ID
     * @return
     */
    @GetMapping("nextId")
    public JsonResult nextId(Integer currentId) {
        Integer id = this.service.getNextId(this.accountSetsId, currentId);
        return JsonResult.successful(id);
    }

    @PostMapping("/save")
    public JsonResult save(@RequestPart("voucher")  Voucher voucher,@RequestPart("fileList") List<MultipartFile> fileList) {
        System.out.println(voucher);
        for (VoucherDetails detail : voucher.getDetails()) {
            StringBuilder subjectCode = new StringBuilder();
            for (AccountingCategoryDetails accountingCategoryDetails : detail.getAuxiliary()) {
                subjectCode.append("_").append(accountingCategoryDetails.getCode());
            }
            detail.setSubjectCode(detail.getSubjectCode() + subjectCode);
        }
        String exist = checkExistSonSubject(voucher.getDetails());
        if (!exist.equals("false")){
            return JsonResult.failure(exist);
        }
        Voucher entity = voucher;
        entity.setDocNum(String.valueOf(fileList.size()));


        JsonResult result = super.save(entity);

        if (result.getData().equals(0)){
            return JsonResult.failure("凭证字号已存在");
        }else {
            //判断凭证时间创建结账期
            checkoutService.checkTime(this.accountSetsId,voucher.getVoucherDate());
            if (result.isSuccess()) {
                DateFormat sdf = new SimpleDateFormat("yyyyMM");
                if (!sdf.format(this.currentUser.getAccountSets().getCurrentAccountDate()).equals(entity.getVoucherDate())) {
                    redisUtil.setAttribute(this.userService.getUserVo(this.currentUser.getId()),this.session);
                }
            }
//        result.setData(entity);

            //附件上传
            System.out.println("附件上传");
            FileBean fileBean = new FileBean();
            fileBean.setFileList(fileList);
            fileBean.setAccountSetsId(entity.getAccountSetsId());
            fileBean.setVoucherId(entity.getId());
            fileManageController.uploadAppendix(fileBean);

            List<FileBean> fileBeanList = fileMapper.findFileBean(entity.getAccountSetsId(), entity.getId());
            HashMap<Object, Object> hashMap = new HashMap<>();
            hashMap.put("voucher",entity);
            hashMap.put("fileBeanList",fileBeanList);
            result.setData(hashMap);

            return result;
        }

    }

    //检查当前科目是否存在子科目
    private String checkExistSonSubject(List<VoucherDetails> details) {

        List<Integer> idList = new ArrayList<>();
        for (VoucherDetails detail : details) {
            idList.add(detail.getSubjectId());
        }
        List<Integer> collect = idList.stream().distinct().collect(Collectors.toList());
        QueryWrapper<Subject> qw = new QueryWrapper<>();
        qw.in("parent_id",collect);
        List<Subject> subjects = subjectService.list(qw);
        if (subjects.size() == 0){
            return "false";
        }else {
            for (Subject subject : subjects) {
                Integer parentId = subject.getParentId();
                for (VoucherDetails detail : details) {
                    if (parentId.equals(detail.getSubjectId())){
                        System.out.println(detail.getSubjectName()+"---存在子科目");
                        return detail.getSubjectName()+"---存在子科目";
                    }
                }
            }
            return "保存出错！";
        }
    }

    @GetMapping("summary")
    public JsonResult summary() {
        List<String> summary = this.service.getTopSummary(this.accountSetsId);
        summary = summary.stream().map(String::trim).collect(Collectors.toList());
        for (String s : defaultSummary) {
            if (!summary.contains(s)) {
                summary.add(s);
            }
        }
        return JsonResult.successful(summary);
    }

    @PostMapping("/import")
    public JsonResult importVoucher(@RequestParam("file") MultipartFile multipartFile) {
        try {
            List<Voucher> voucherList = excelUtils.readExcel(multipartFile.getOriginalFilename(), multipartFile.getInputStream(), this.currentUser);
            Date date = this.service.importVoucher(voucherList, this.currentUser.getAccountSets());
            redisUtil.setAttribute(this.userService.getUserVo(this.currentUser.getId()),this.session);
            return JsonResult.successful(date);
        } catch (ServiceException e) {
            return JsonResult.failure(e.getMessage());
        } catch (Exception e) {
            log.error("导入失败", e);
            throw new ServiceException("导入失败~", e);
        }
    }
}
